package com.ruoyi.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.platform.constant.UserConstants;
import com.ruoyi.platform.service.impl.BaseServiceImpl;
import com.ruoyi.domain.Document;
import com.ruoyi.domain.DocumentCategory;
import com.ruoyi.dto.CategoryTree;
import com.ruoyi.mapper.DocumentCategoryMapper;
import com.ruoyi.platform.utils.BeanUtils;
import com.ruoyi.platform.utils.StringUtils;
import com.ruoyi.service.IDocumentCategoryService;
import com.ruoyi.service.IDocumentService;
import com.ruoyi.utils.BaseFileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 文档目录Service业务层处理
 *
 * @author tp
 * @date 2022-11-02
 */
@Service
public class DocumentCategoryServiceImpl extends BaseServiceImpl<DocumentCategoryMapper, DocumentCategory> implements IDocumentCategoryService {

    @Autowired
    private DocumentCategoryMapper documentCategoryMapper;

    @Autowired
    @Lazy
    private IDocumentService documentService;

    @Autowired
    private BaseFileUtils baseFileUtils;

    /**
     * 查询文档目录
     *
     * @param id 文档目录主键
     * @return 文档目录
     */
    @Override
    public DocumentCategory selectDocumentCategoryById(Long id) {
        return documentCategoryMapper.selectDocumentCategoryById(id);
    }

    /**
     * 查询文档目录列表
     *
     * @param documentCategory 文档目录
     * @return 文档目录
     */
    @Override
    public List<DocumentCategory> selectDocumentCategoryList(DocumentCategory documentCategory) {
        return documentCategoryMapper.selectDocumentCategoryList(documentCategory);
    }

    /**
     * 新增文档目录
     *
     * @param documentCategory 文档目录
     * @return 结果
     */
    @Transactional
    @Override
    public int insertDocumentCategory(DocumentCategory documentCategory) {
        int flag = 0;
        DocumentCategory info = new DocumentCategory();
        if(documentCategory.getIsRoot()!=1) {
             info = getById(documentCategory.getParentId());
            Assert.notNull(info, "当前文档目录不存在");
            documentCategory.setCategoryType(info.getCategoryType());
            documentCategory.setAncestors(info.getAncestors() + "," + documentCategory.getParentId());
        }else{
            documentCategory.setAncestors(String.valueOf(documentCategory.getParentId()));
        }
        boolean save = save(documentCategory);
        if (save) {
            flag = 1;
        }
        return flag;
    }

    /**
     * 修改文档目录
     *
     * @param documentCategory 文档目录
     * @return 结果
     */
    @Transactional
    @Override
    public int updateDocumentCategory(DocumentCategory documentCategory) {
        DocumentCategory newParent = getById(documentCategory.getParentId());
        DocumentCategory old = getById(documentCategory.getId());
        Assert.isTrue(!UserConstants.NOT_UNIQUE.equals(checkCategoryNameUnique(documentCategory)), "失败，文档目录名称已存在");
        Assert.isTrue(!UserConstants.NOT_UNIQUE.equals(checkCategoryNameUnique(documentCategory)), "修改文档目录'" + documentCategory.getCategoryName() + "'失败，上级不能是自己");
        if (StringUtils.isNotNull(newParent) && StringUtils.isNotNull(old)) {
            String newAncestors = newParent.getAncestors() + "," + newParent.getId();
            String oldAncestors = old.getAncestors();
            documentCategory.setAncestors(newAncestors);
            updateChildren(documentCategory.getId(), newAncestors, oldAncestors);
        }

        return documentCategoryMapper.updateById(documentCategory);
    }

    /**
     * 修改子元素关系
     *
     * @param id           被修改的目录ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    @Transactional
    public void updateChildren(Long id, String newAncestors, String oldAncestors) {
        List<DocumentCategory> children = baseMapper.selectChildrenById(id);
        for (DocumentCategory child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            baseMapper.updateChildren(children);
        }
    }

    /**
     * 批量删除文档目录
     *
     * @param ids 需要删除的文档目录主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteDocumentCategoryByIds(Long[] ids) {
        return documentCategoryMapper.deleteDocumentCategoryByIds(ids);
    }

    /**
     * 删除文档目录信息
     *
     * @param id 文档目录主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteDocumentCategoryById(Long id) {
        return documentCategoryMapper.deleteDocumentCategoryById(id);
    }

    /**
     * 校验文档目录名称是否唯一
     *
     * @param documentCategory 目录信息
     * @return
     */
    @Override
    public String checkCategoryNameUnique(DocumentCategory documentCategory) {
        Long id = StringUtils.isNull(documentCategory.getId()) ? -1L : documentCategory.getId();
        LambdaQueryWrapper<DocumentCategory> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DocumentCategory::getCategoryName, documentCategory.getCategoryName())
                .eq(DocumentCategory::getParentId, documentCategory.getParentId()).eq(DocumentCategory::getDelFlag, "0");
        DocumentCategory info = getOne(queryWrapper);
        if (StringUtils.isNotNull(info) && info.getId().longValue() != id.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    @Transactional
    public int deleteById(Long id) {
        int flag = 0;
        Assert.isFalse(hasChildById(id), "存在下级目录,不允许删除");
        Assert.isFalse(checkExistDocument(id), "目录拥有文档,不允许删除");
        boolean b = removeById(id);
        if (b) {
            flag = 1;
        }
        return flag;
    }

    /**
     * 加载文档目录树
     *
     * @param documentCategory
     * @return
     */
    @Override
    public List<CategoryTree> getTreeList(DocumentCategory documentCategory) {
        List<DocumentCategory> list = documentCategoryMapper.selectDocumentCategoryList(documentCategory);
        List<CategoryTree> treeList = buildCategoryTreeList(list);
        return treeList;
    }

    @Override
    public int deleteCategoryByDocName(String docName) {
        return documentCategoryMapper.deleteCategoryByDocName(docName);
    }

    @Override
    public DocumentCategory getCategoryByDocName(String docName) {
        return documentCategoryMapper.selectByCategoryName(docName);
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param list
     * @return 下拉树结构列表
     */
    private List<CategoryTree> buildCategoryTreeList(List<DocumentCategory> list) {
        List<DocumentCategory> trees = buildCategoryTree(list);
        return trees.stream().map(CategoryTree::new).collect(Collectors.toList());
    }

    private List<DocumentCategory> buildCategoryTree(List<DocumentCategory> list) {
        List<DocumentCategory> returnList = new ArrayList<>();
        List<Long> tempList = list.stream().map(x -> x.getId()).collect(Collectors.toList());
        for (DocumentCategory d : list) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(d.getParentId())) {
                recursionFn(list, d);
                returnList.add(d);
            }
        }
        if (returnList.isEmpty()) {
            returnList = list;
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param d
     */
    private void recursionFn(List<DocumentCategory> list, DocumentCategory d) {
        // 得到子节点列表
        List<DocumentCategory> childList = getChildList(list, d);
        d.setChildren(childList);
        for (DocumentCategory tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<DocumentCategory> getChildList(List<DocumentCategory> list, DocumentCategory t) {
        List<DocumentCategory> tList = new ArrayList<>();
        Iterator<DocumentCategory> it = list.iterator();
        while (it.hasNext()) {
            DocumentCategory n = it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
                if (BeanUtils.isNotEmpty(n.getDocumentId()) && n.getDocumentId() > 0L) {
                    Document document = documentService.get(n.getDocumentId());
                    if (BeanUtils.isNotEmpty(document)) {
                        String fileUrl = baseFileUtils.getFileUrlById(document.getFileId().toString());
                        if (fileUrl.lastIndexOf(".") != -1) {
                            n.setType(fileUrl.substring(fileUrl.lastIndexOf(".")+1));
                        }
                    }
                }
                tList.add(n);
            }
        }
        return tList;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<DocumentCategory> list, DocumentCategory t) {
        return getChildList(list, t).size() > 0;
    }

    private boolean checkExistDocument(Long id) {
        LambdaQueryWrapper<Document> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Document::getId, id).eq(Document::getDelFlag, 0).last("limit 1");
        int count = documentService.count(queryWrapper);
        return count > 0;
    }

    private boolean hasChildById(Long id) {
        LambdaQueryWrapper<DocumentCategory> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DocumentCategory::getParentId, id).eq(DocumentCategory::getDelFlag, 0).last("limit 1");
        int count = count(queryWrapper);
        return count > 0;
    }

    /**
     * 查询文档分类中的第一个文档
     *
     * @return 最小document_id
     */
    @Override
    public DocumentCategory selectFirstFile() {
        return documentCategoryMapper.selectFirstFile();
    }


}
